
#include <cstdio>
#include <BThread>
#include "member_BThread.h"

using namespace BWE;

#define member					(*(member_BThread*)_ptr)
#define member_allocate()		_ptr = new member_BThread(this)
#define member_release()		delete (member_BThread*)_ptr

#ifdef _LINUX_

void* thead_routine(void* parameter)
{
    sleep(1);
	BThread* thread = (BThread*)parameter;
	if(thread)
		thread->run();
	return 0;
}

BThread::BThread()
{
	member_allocate();
	int ret = pthread_create(&member.thread, 0, thead_routine, this);
	if(ret)
		puts("failed to create thread !!");
}
BThread::~BThread()
{
	pthread_detach(member.thread);
	member_release();
}

bool BThread::sleep(double seconds)
{
	member.sleeping = false;
	if(seconds < 0)
		return true;
	if(seconds > 0)
		return false;
	return member.sleeping;
}

bool BThread::wake()
{
	return member.sleeping;
}
bool BThread::wait()
{
	return false;
}

bool BThread::quit()
{
	member.quit = true;
	wait();
	return true;
}

bool BThread::isOver() const
{
	bool over = member.quit;
	return member.quit;
}
bool BThread::isSleeping() const
{
	return member.sleeping;
}

#endif

#ifdef _WINDOWS_SYSTEM_

DWORD WINAPI thread_routine(void* param)
{
	BThread* thread = (BThread*)param;
	while (thread && !thread_member(thread)->done)
	{
		thread->run();
		thread->stop();
	}
	return 0;
}

BThread::BThread()
{
	member_allocate();
	member.handle = ::CreateThread(0, 0, thread_routine, this, CREATE_SUSPENDED, &member.ID);
}
BThread::~BThread()
{
	if(member.handle)
		::CloseHandle(member.handle);
	if(member.htimer)
		::CloseHandle(member.htimer);
	member_release();
}

bool BThread::wait()
{
	DWORD ret = WaitForSingleObject(member.handle, INFINITE);
	return ret != WAIT_FAILED;
}

bool BThread::sleep(double seconds)
{
	member.sleeping = false;

	if(seconds <= 0.0)
		return true;

	if(seconds < 0)
	{
		member.sleeping = !SuspendThread(member.handle);
		return member.sleeping;
	}

	if(member.htimer == 0)
		member.htimer = ::CreateWaitableTimer(0, true, 0);

	if(member.htimer == 0)
		return false;

	LARGE_INTEGER time;
	time.QuadPart = seconds * -10000000;

	if(::SetWaitableTimer(member.htimer, &time, 0, 0, 0, 0) == false)
		return false;

	if(::WaitForSingleObject(member.htimer, INFINITE) == WAIT_FAILED)
		return false;

	return true;
}

bool BThread::exit(int code)
{
	if (member.handle)
	{
		member.done = true;
		member.exitcode = code;
		if (member.sleeping)
			start();
		return true;
	}
	return false;
}
bool BThread::terminate(int code)
{
	if (member.handle)
	{
		member.done = true;
		member.exitcode = code;
		TerminateThread(member.handle, code);
		CloseHandle(member.handle);
		member.handle = 0;
		return true;
	}
	return false;
}

bool BThread::start()
{
	if (member.handle && member.sleeping)
	{
		DWORD ret = ResumeThread(member.handle);
		member.sleeping = false;
		return true;
	}
	return false;
}
bool BThread::stop()
{
	if (member.handle && !member.sleeping)
	{
		member.sleeping = true;
		DWORD ret = SuspendThread(member.handle);
		return true;
	}
	return true;
}

bool BThread::done() const
{
	return member.done;
}
bool BThread::sleeping() const
{
	return member.sleeping;
}

#endif

